<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
    <title>Loading Plugins - Zend Framework Manual</title>

    <link href="../css/shCore.css" rel="stylesheet" type="text/css" />
    <link href="../css/shThemeDefault.css" rel="stylesheet" type="text/css" />
    <link href="../css/styles.css" media="all" rel="stylesheet" type="text/css" />
</head>
<body>
<h1>Zend Framework</h1>
<h2>Programmer's Reference Guide</h2>
<ul>
    <li><a href="../en/zend.loader.pluginloader.html">Inglês (English)</a></li>
    <li><a href="../pt-br/zend.loader.pluginloader.html">Português Brasileiro (Brazilian Portuguese)</a></li>
</ul>
<table width="100%">
    <tr valign="top">
        <td width="85%">
            <table width="100%">
                <tr>
                    <td width="25%" style="text-align: left;">
                    <a href="zend.loader.autoloader-resource.html">Resource Autoloaders</a>
                    </td>

                    <td width="50%" style="text-align: center;">
                        <div class="up"><span class="up"><a href="zend.loader.html">Zend_Loader</a></span><br />
                        <span class="home"><a href="manual.html">Programmer's Reference Guide</a></span></div>
                    </td>

                    <td width="25%" style="text-align: right;">
                        <div class="next" style="text-align: right; float: right;"><a href="zend.locale.html">Zend_Locale</a></div>
                    </td>
                </tr>
            </table>
<hr />
<div id="zend.loader.pluginloader" class="section"><div class="info"><h1 class="title">Loading Plugins</h1></div>
    

    <p class="para">
        A number of Zend Framework components are pluggable, and allow loading
        of dynamic functionality by specifying a class prefix and path to class
        files that are not necessarily on the <span class="property">include_path</span> or do
        not necessarily follow traditional naming conventions.
        <span class="classname">Zend_Loader_PluginLoader</span> provides common functionality for
        this process.
    </p>

    <p class="para">
        The basic usage of the <span class="classname">PluginLoader</span> follows Zend Framework
        naming conventions of one class per file, using the underscore as a
        directory separator when resolving paths. It allows passing an optional
        class prefix to prepend when determining if a particular plugin class is
        loaded. Additionally, paths are searched in LIFO order. Due to the LIFO
        search and the class prefixes, this allows you to define namespaces for your
        plugins, and thus override plugins from paths registered earlier.
    </p>

    <div class="section" id="zend.loader.pluginloader.usage"><div class="info"><h1 class="title">Basic Use Case</h1></div>
        

        <p class="para">
            First, let&#039;s assume the following directory structure and class
            files, and that the top level directory and library directory are on
            the include_path:
        </p>

        <pre class="programlisting brush: txt">
application/
    modules/
        foo/
            views/
                helpers/
                    FormLabel.php
                    FormSubmit.php
        bar/
            views/
                helpers/
                    FormSubmit.php
library/
    Zend/
        View/
            Helper/
                FormLabel.php
                FormSubmit.php
                FormText.php
</pre>


        <p class="para">
            Now, let&#039;s create a plugin loader to address the various view
            helper repositories available:
        </p>

        <pre class="programlisting brush: php">
$loader = new Zend_Loader_PluginLoader();
$loader-&gt;addPrefixPath(&#039;Zend_View_Helper&#039;, &#039;Zend/View/Helper/&#039;)
       -&gt;addPrefixPath(&#039;Foo_View_Helper&#039;,
                       &#039;application/modules/foo/views/helpers&#039;)
       -&gt;addPrefixPath(&#039;Bar_View_Helper&#039;,
                       &#039;application/modules/bar/views/helpers&#039;);
</pre>


        <p class="para">
            We can then load a given view helper using just the portion of the
            class name following the prefixes as defined when adding the paths:
        </p>

        <pre class="programlisting brush: php">
// load &#039;FormText&#039; helper:
$formTextClass = $loader-&gt;load(&#039;FormText&#039;); // &#039;Zend_View_Helper_FormText&#039;;

// load &#039;FormLabel&#039; helper:
$formLabelClass = $loader-&gt;load(&#039;FormLabel&#039;); // &#039;Foo_View_Helper_FormLabel&#039;

// load &#039;FormSubmit&#039; helper:
$formSubmitClass = $loader-&gt;load(&#039;FormSubmit&#039;); // &#039;Bar_View_Helper_FormSubmit&#039;
</pre>


        <p class="para">
            Once the class is loaded, we can now instantiate it.
        </p>

        <blockquote class="note"><p><b class="note">Note</b>: 
            <p class="para">
                In some cases, you may use the same prefix for multiple paths.
                <span class="classname">Zend_Loader_PluginLoader</span> actually registers an
                array of paths for each given prefix; the last one registered
                will be the first one checked. This is particularly useful if
                you are utilizing incubator components.
            </p>
        </p></blockquote>

        <blockquote class="note"><p><b class="note">Note</b>: <span class="info"><b>Paths may be defined at instantiation</b><br /></span>
            

            <p class="para">
                You may optionally provide an array of prefix / path pairs (or
                prefix / paths -- plural paths are allowed) as a parameter to
                the constructor:
            </p>

            <pre class="programlisting brush: php">
$loader = new Zend_Loader_PluginLoader(array(
    &#039;Zend_View_Helper&#039; =&gt; &#039;Zend/View/Helper/&#039;,
    &#039;Foo_View_Helper&#039;  =&gt; &#039;application/modules/foo/views/helpers&#039;,
    &#039;Bar_View_Helper&#039;  =&gt; &#039;application/modules/bar/views/helpers&#039;
));
</pre>

        </p></blockquote>

        <p class="para">
            <span class="classname">Zend_Loader_PluginLoader</span> also optionally allows you to
            share plugins across plugin-aware objects, without needing to
            utilize a singleton instance. It does so via a static registry.
            Indicate the registry name at instantiation as the second parameter
            to the constructor:
        </p>

        <pre class="programlisting brush: php">
// Store plugins in static registry &#039;foobar&#039;:
$loader = new Zend_Loader_PluginLoader(array(), &#039;foobar&#039;);
</pre>


        <p class="para">
            Other components that instantiate the <span class="classname">PluginLoader</span>
            using the same registry name will then have access to already loaded
            paths and plugins.
        </p>
    </div>

    <div class="section" id="zend.loader.pluginloader.paths"><div class="info"><h1 class="title">Manipulating Plugin Paths</h1></div>
        

        <p class="para">
            The example in the previous section shows how to add paths to a
            plugin loader. What if you want to determine the paths already
            loaded, or remove one or more?
        </p>

        <ul class="itemizedlist">
            <li class="listitem">
                <p class="para">
                     <span class="methodname">getPaths($prefix = null)</span> returns all paths as
                    prefix / path pairs if no <var class="varname">$prefix</var> is provided,
                    or just the paths registered for a given prefix if a
                    <var class="varname">$prefix</var> is present.
                </p>
            </li>

            <li class="listitem">
                <p class="para">
                     <span class="methodname">clearPaths($prefix = null)</span> will clear all
                    registered paths by default, or only those associated with a
                    given prefix, if the <var class="varname">$prefix</var> is provided and
                    present in the stack.
                </p>
            </li>

            <li class="listitem">
                <p class="para">
                     <span class="methodname">removePrefixPath($prefix, $path = null)</span> allows
                    you to selectively remove a specific path associated with a
                    given prefix. If no <var class="varname">$path</var> is provided, all
                    paths for that prefix are removed. If a <var class="varname">$path</var>
                    is provided and exists for that prefix, only that path will
                    be removed.
                </p>
            </li>
        </ul>
    </div>

    <div class="section" id="zend.loader.pluginloader.checks"><div class="info"><h1 class="title">Testing for Plugins and Retrieving Class Names</h1></div>
        

        <p class="para">
            Sometimes you simply want to determine if a plugin class has been
            loaded before you perform an action.  <span class="methodname">isLoaded()</span> takes a
            plugin name, and returns the status.
        </p>

        <p class="para">
            Another common use case for the <span class="classname">PluginLoader</span> is to
            determine fully qualified plugin class names of loaded classes;
             <span class="methodname">getClassName()</span> provides this functionality. Typically,
            this would be used in conjunction with  <span class="methodname">isLoaded()</span>:
        </p>

        <pre class="programlisting brush: php">
if ($loader-&gt;isLoaded(&#039;Adapter&#039;)) {
    $class   = $loader-&gt;getClassName(&#039;Adapter&#039;);
    $adapter = call_user_func(array($class, &#039;getInstance&#039;));
}
</pre>

    </div>

    <div class="section" id="zend.loader.pluginloader.performance"><div class="info"><h1 class="title">Getting Better Performance for Plugins</h1></div>
        

        <p class="para">
            Plugin loading can be an expensive operation. At its heart, it needs
            to loop through each prefix, then each path on the prefix, until it
            finds a file that matches -- and which defines the class expected.
            In cases where the file exists but does not define the class, an
            error will be added to the <acronym class="acronym">PHP</acronym> error stack, which is also an
            expensive operation. The question then turns to: how can you keep
            the flexibility of plugins and also address performance?
        </p>

        <p class="para">
            <span class="classname">Zend_Loader_PluginLoader</span> offers an opt-in feature for
            just this situation, a class file include cache. When enabled, it
            will create a file that contains all successful includes which you
            can then call from your bootstrap. Using this strategy, you can
            greatly improve the performance of your production servers.
        </p>

        <div class="example" id="zend.loader.pluginloader.performance.example"><div class="info"><p><b>Example #1 Using the PluginLoader class file include cache</b></p></div>
            

            <div class="example-contents"><p>
                To use the class file include cache, simply drop the
                following code into your bootstrap:
            </p></div>

            <pre class="programlisting brush: php">
$classFileIncCache = APPLICATION_PATH . &#039;/../data/pluginLoaderCache.php&#039;;
if (file_exists($classFileIncCache)) {
    include_once $classFileIncCache;
}
Zend_Loader_PluginLoader::setIncludeFileCache($classFileIncCache);
</pre>


            <div class="example-contents"><p>
                Obviously, the path and filename will vary based on your needs.
                This code should come as early as possible, to ensure that
                plugin-based components can make use of it.
            </p></div>

            <div class="example-contents"><p>
                During development, you may wish to disable the cache. One
                method for doing so is to use a configuration key for
                determining whether or not the plugin loader should cache.
            </p></div>

            <pre class="programlisting brush: php">
$classFileIncCache = APPLICATION_PATH . &#039;/../data/pluginLoaderCache.php&#039;;
if (file_exists($classFileIncCache)) {
    include_once $classFileIncCache;
}
if ($config-&gt;enablePluginLoaderCache) {
    Zend_Loader_PluginLoader::setIncludeFileCache($classFileIncCache);
}
</pre>


            <div class="example-contents"><p>
                This technique allows you to keep your modifications to your
                configuration file rather than code.
            </p></div>
        </div>
    </div>
</div>
        <hr />

            <table width="100%">
                <tr>
                    <td width="25%" style="text-align: left;">
                    <a href="zend.loader.autoloader-resource.html">Resource Autoloaders</a>
                    </td>

                    <td width="50%" style="text-align: center;">
                        <div class="up"><span class="up"><a href="zend.loader.html">Zend_Loader</a></span><br />
                        <span class="home"><a href="manual.html">Programmer's Reference Guide</a></span></div>
                    </td>

                    <td width="25%" style="text-align: right;">
                        <div class="next" style="text-align: right; float: right;"><a href="zend.locale.html">Zend_Locale</a></div>
                    </td>
                </tr>
            </table>
</td>
        <td style="font-size: smaller;" width="15%"> <style type="text/css">
#leftbar {
	float: left;
	width: 186px;
	padding: 5px;
	font-size: smaller;
}
ul.toc {
	margin: 0px 5px 5px 5px;
	padding: 0px;
}
ul.toc li {
	font-size: 85%;
	margin: 1px 0 1px 1px;
	padding: 1px 0 1px 11px;
	list-style-type: none;
	background-repeat: no-repeat;
	background-position: center left;
}
ul.toc li.header {
	font-size: 115%;
	padding: 5px 0px 5px 11px;
	border-bottom: 1px solid #cccccc;
	margin-bottom: 5px;
}
ul.toc li.active {
	font-weight: bold;
}
ul.toc li a {
	text-decoration: none;
}
ul.toc li a:hover {
	text-decoration: underline;
}
</style>
 <ul class="toc">
  <li class="header home"><a href="manual.html">Programmer's Reference Guide</a></li>
  <li class="header up"><a href="manual.html">Programmer's Reference Guide</a></li>
  <li class="header up"><a href="reference.html">Zend Framework Reference</a></li>
  <li class="header up"><a href="zend.loader.html">Zend_Loader</a></li>
  <li><a href="zend.loader.load.html">Loading Files and Classes Dynamically</a></li>
  <li><a href="zend.loader.autoloader.html">The Autoloader</a></li>
  <li><a href="zend.loader.autoloader-resource.html">Resource Autoloaders</a></li>
  <li class="active"><a href="zend.loader.pluginloader.html">Loading Plugins</a></li>
 </ul>
 </td>
    </tr>
</table>

<script type="text/javascript" src="../js/shCore.js"></script>
<script type="text/javascript" src="../js/shAutoloader.js"></script>
<script type="text/javascript" src="../js/main.js"></script>

</body>
</html>